/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package agenda.database;

import agenda.entityes.AgeEntry;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;

/**
 *
 * @author emanuele
 */
public class DBManager {

    public static enum SearchType {

        Nome, Cognome, Azienda, eMail
    };
    private boolean canWrite = true;
    private AgeDB database = new AgeDB();
    private AgeParser dbParser;
    private File dbFile;

    public void openDB(File f) throws FileNotFoundException, ParseException {
        if (f == null) {
            throw new IllegalArgumentException();
        }

        dbFile = f;
        if (f.length() > 10) {

            dbParser = new AgeParser(new FileInputStream(f));

            dbParser.parseFile();
            database = dbParser.getDB();
        } else {
            System.out.println("gnignignignginginginging");
        }

    }

    public boolean canWritte() {
        return canWrite;
    }

    public boolean addEntry(AgeEntry e) {
        if (!canWrite) {
            throw new IllegalStateException("Scrittura disabilitata");
        }
        if (e == null) {
            throw new IllegalArgumentException();
        }
        return database.addEntry(e);
    }

    public boolean delEntry(AgeEntry e) {
        if (!canWrite || e == null) {
            return false;
        }
        return database.delEntry(e);
    }

    /**
     * Esegue la ricerca degli elementi che hanno determinate caratteristiche.
     * Se in &egrave; @code {false} esegue la ricerca con @code{contains} all'interno
     * del campo stabilito da @code{st} altrimenti verifico se la stringa s &egrave; un prefisso
     * del campo.
     * @param st tipo di campo per il quale effettuare la ricerca
     * @param list lista nella quale eseguire la ricerca
     * @param s stringa da ricercare
     * @param cs se true la ricerca viene eseguita con distinzione di maiuscole
     * @param pr se true la ricerca verifica linterpretando la tringa come prefisso
     * @return
     */
    public static List<AgeEntry> search(SearchType st, List<AgeEntry> list, String s, boolean cs, boolean lk) {
        List<AgeEntry> out = new LinkedList<AgeEntry>() {

            @Override
            public boolean add(AgeEntry e) {
                if (!contains(e)) {
                    return super.add(e);
                } else {
                    return false;
                }
            }
        };


            switch (st) {
            case Nome:
                for (AgeEntry e : list) {
                    if (cs ? e.getName().contains(s) : e.getName().toUpperCase().contains(s.toUpperCase())) {
                        out.add(e);// trovato corrispondente
                        // ora aggiungi tutti i collegati
                        for (AgeEntry x : list) {
                            if (lk && x.containsAssociation(e)) {
                                out.add(x);
                            }
                        }
                    }
                }
                break;
            case Cognome:
                for (AgeEntry e : list) {
                    if (cs ? e.getSurname().contains(s) : e.getSurname().toUpperCase().contains(s.toUpperCase())) {
                        out.add(e);// trovato corrispondente
                        // ora aggiungi tutti i collegati
                        for (AgeEntry x : list) {
                            if (lk && x.containsAssociation(e)) {
                                out.add(x);
                            }
                        }
                    }
                }
                break;
            //TODO forse il nome dell'azienda è meglio salvarlo nel campo nome
            // invece che in cognome
            case Azienda:
                for (AgeEntry e : list) {
                    if (cs ? e.getSurname().contains(s) : e.getSurname().toUpperCase().contains(s.toUpperCase())) {
                        out.add(e);// trovato corrispondente
                        // ora aggiungi tutti i collegati
                        for (AgeEntry x : list) {
                            if (lk && x.containsAssociation(e)) {
                                out.add(x);
                            }
                        }
                    }
                }
                break;
            case eMail:
                for (AgeEntry e : list) {
                    if (cs ? e.getEmail().contains(s) : e.getEmail().toUpperCase().contains(s.toUpperCase())) {
                        out.add(e);// trovato corrispondente
                        // ora aggiungi tutti i collegati
                        for (AgeEntry x : list) {
                            if (lk && x.containsAssociation(e)) {
                                out.add(x);
                            }
                        }
                    }
                }
        }


        return out;
    }

    public static List<AgeEntry> prefixSearch(SearchType st, List<AgeEntry> list, String s, boolean cs, boolean lk) {
       if (list == null)
               return null;

        List<AgeEntry> out = new LinkedList<AgeEntry>() {

            @Override
            public boolean add(AgeEntry e) {
                if (!contains(e)) {
                    return super.add(e);
                } else {
                    return false;
                }
            }
        };

        switch (st) {
            case Nome:
                for (AgeEntry e : list) {
                    if (cs ? e.getName().startsWith(s) : e.getName().toUpperCase().startsWith(s.toUpperCase())) {
                        out.add(e);// trovato corrispondente
                        // ora aggiungi tutti i collegati
                        for (AgeEntry x : list) {
                            if (lk && x.containsAssociation(e)) {
                                out.add(x);
                            }
                        }
                    }
                }
                break;
            case Cognome:
                for (AgeEntry e : list) {
                    if (cs ? e.getSurname().startsWith(s) : e.getSurname().toUpperCase().startsWith(s.toUpperCase())) {
                        out.add(e);// trovato corrispondente
                        // ora aggiungi tutti i collegati
                        for (AgeEntry x : list) {
                            if (lk && x.containsAssociation(e)) {
                                out.add(x);
                            }
                        }
                    }
                }
                break;
            //TODO forse il nome dell'azienda è meglio salvarlo nel campo nome
            // invece che in cognome
            case Azienda:
                for (AgeEntry e : list) {
                    if (cs ? e.getSurname().startsWith(s) : e.getSurname().toUpperCase().startsWith(s.toUpperCase())) {
                        out.add(e);// trovato corrispondente
                        // ora aggiungi tutti i collegati
                        for (AgeEntry x : list) {
                            if (lk && x.containsAssociation(e)) {
                                out.add(x);
                            }
                        }
                    }
                }
                break;
            case eMail:
                for (AgeEntry e : list) {
                    if (cs ? e.getEmail().startsWith(s) : e.getEmail().toUpperCase().startsWith(s.toUpperCase())) {
                        out.add(e);// trovato corrispondente
                        // ora aggiungi tutti i collegati
                        for (AgeEntry x : list) {
                            if (lk && x.containsAssociation(e)) {
                                out.add(x);
                            }
                        }
                    }
                }
        }
        return out;
    }

    public List<AgeEntry> getAllEntries() {
        return Collections.unmodifiableList(database.entries);
    }

    public AgeDB getDatabase() {
        return database;
    }

    public void saveToFile() throws FileNotFoundException {
        DBWriter.writeToFile(database, dbFile);
    }
}
